package com.framework.mapper.generator.godeGenerator.custom;

import com.framework.common.util.hump.HumpOrLineUtil;
import com.framework.common.util.other.NumeralUtil;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.mybatis3.ListUtilities;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import org.mybatis.generator.codegen.mybatis3.xmlmapper.elements.AbstractXmlElementGenerator;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author 龘鵺
 * @version 1.0
 * @className com.framework.mapper.generator.godeGenerator.custom
 * @description 自定义xml配置文件类
 * @datetime 2022-01-09 11:11:11
 */
public class CustomAbstractXmlElementGenerator extends AbstractXmlElementGenerator {
    private Map<String, Integer> jdbcTypeMap = new HashMap<String, Integer>(NumeralUtil.POSITIVE_TWO);
    private Map<String, Integer> columnMap = new HashMap<String, Integer>(NumeralUtil.POSITIVE_EIGHT);
    private Map<String, Integer> insertFilterMap = new HashMap<String, Integer>(NumeralUtil.POSITIVE_EIGHT);
    private Map<String, Integer> updateFilterMap = new HashMap<String, Integer>(NumeralUtil.POSITIVE_EIGHT);
    private Map<String, Integer> filterMap = new HashMap<String, Integer>(NumeralUtil.POSITIVE_EIGHT);
    private Map<String, Integer> deleteMap = new HashMap<String, Integer>(NumeralUtil.POSITIVE_EIGHT);
    private Map<String, Integer> batchDeleteListMap = new HashMap<String, Integer>(NumeralUtil.POSITIVE_EIGHT);
    private Map<String, Integer> isExistFilterMap = new HashMap<String, Integer>(NumeralUtil.POSITIVE_EIGHT);
    private boolean isStatus = false;
    private boolean isPublicWhereStatus = false;
    private boolean isPublicWhereUserId = false;
    private boolean isPublicWhereCreateTime = false;

    // model 前缀
    private String modelVoPreffix;

    // model 后缀
    private String modelVoSuffix;

    //类路径
    private String classVoPath = "";

    /**
     * 生成什么端的代码： back=后台端， api=用户端
     */
    private String item = "";

    public CustomAbstractXmlElementGenerator(Properties properties) {
        jdbcTypeMap.put("VARCHAR", NumeralUtil.POSITIVE_ONE);
        jdbcTypeMap.put("LONGVARCHAR", NumeralUtil.POSITIVE_ONE);
        columnMap.put("id", NumeralUtil.POSITIVE_ZERO);
        insertFilterMap.put("id", NumeralUtil.POSITIVE_ZERO);
        updateFilterMap.put("id", NumeralUtil.POSITIVE_ZERO);
        updateFilterMap.put("createId", NumeralUtil.POSITIVE_ZERO);
        updateFilterMap.put("createTime", NumeralUtil.POSITIVE_ZERO);
        filterMap.put("createId", NumeralUtil.POSITIVE_ZERO);
        filterMap.put("createTime", NumeralUtil.POSITIVE_ZERO);
        filterMap.put("operaterId", NumeralUtil.POSITIVE_ZERO);
        filterMap.put("operaterTime", NumeralUtil.POSITIVE_ZERO);
        filterMap.put("operaterStatus", NumeralUtil.POSITIVE_ZERO);
        isExistFilterMap.put("createId", NumeralUtil.POSITIVE_ZERO);
        isExistFilterMap.put("createTime", NumeralUtil.POSITIVE_ZERO);
        isExistFilterMap.put("operaterId", NumeralUtil.POSITIVE_ZERO);
        isExistFilterMap.put("operaterTime", NumeralUtil.POSITIVE_ZERO);
        isExistFilterMap.put("operaterStatus", NumeralUtil.POSITIVE_ZERO);
//        filterMap.put("LONGVARCHAR", NumeralUtil.POSITIVE_ZERO);
        deleteMap.put("operaterId", NumeralUtil.POSITIVE_ZERO);
        deleteMap.put("operaterTime", NumeralUtil.POSITIVE_ZERO);
        deleteMap.put("operaterStatus", NumeralUtil.POSITIVE_ZERO);
        batchDeleteListMap.put("operaterId", NumeralUtil.POSITIVE_ZERO);
        batchDeleteListMap.put("operaterTime", NumeralUtil.POSITIVE_ZERO);
        batchDeleteListMap.put("operaterStatus", NumeralUtil.POSITIVE_ZERO);
        if (properties != null) {
            item = properties.getProperty("item");
            modelVoPreffix = properties.getProperty("modelVoPreffix");
            modelVoSuffix = properties.getProperty("modelVoSuffix");
        }
    }

    @Override
    public void addElements(XmlElement parentElement) {
        StringBuilder sb = new StringBuilder();
        boolean isCreateId = false;
        boolean isOperaterId = false;
        for (IntrospectedColumn item : introspectedTable.getAllColumns()) {
            if (item.getJavaProperty().equalsIgnoreCase("createId")) {
                isCreateId = true;
            }
            if (item.getJavaProperty().equalsIgnoreCase("operaterId")) {
                isOperaterId = true;
            }
            if (isOperaterId && isCreateId) {
                break;
            }
        }

        StringBuilder selectByRowSB = new StringBuilder();
        StringBuilder isExistSB = new StringBuilder();
        // 公用 select
        sb.append("    select ");
        sb.append("\n        <include refid=\"Base_Column_List\" /> ");

        selectByRowSB.append("    select ");
        selectByRowSB.append("\n        <include refid=\"Base_Column_List\" /> ");

        isExistSB.append("    select ");
        isExistSB.append("    count(p.id) ");

        if (isCreateId && isOperaterId && "back".equalsIgnoreCase(item)) {
            sb.append("\n        , ");
            sb.append("\n        <include refid=\"BaseMapper.publicField\"/> ");
        }
        if (isCreateId && "back".equalsIgnoreCase(item)) {
            sb.append("\n        , <include refid=\"BaseMapper.selectCreateModel\"/>");
        }
        if (isOperaterId && "back".equalsIgnoreCase(item)) {
            sb.append("\n        , <include refid=\"BaseMapper.selectOperaterModel\"/>");
        }
        sb.append("\n        from ");
        sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        sb.append(" p ");

        selectByRowSB.append("\n        from ");
        selectByRowSB.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        selectByRowSB.append(" p ");

        isExistSB.append("\n        from ");
        isExistSB.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        isExistSB.append(" p ");
        if (isCreateId && "back".equalsIgnoreCase(item)) {
            sb.append("\n        <include refid=\"BaseMapper.selectCreateLeft\"/>");
        }
        if (isOperaterId && "back".equalsIgnoreCase(item)) {
            sb.append("\n        <include refid=\"BaseMapper.selectOperaterLeft\"/>");
        }
        TextElement selectText = new TextElement(sb.toString());
        TextElement selectTextRow = new TextElement(selectByRowSB.toString());
        TextElement isExistText = new TextElement(isExistSB.toString());

        // 处理引用视图类路径
        classVoPath = introspectedTable.getBaseRecordType();
        String modelName = classVoPath.substring(classVoPath.lastIndexOf(".") + 1);
        classVoPath = classVoPath.substring(0, classVoPath.lastIndexOf(".") + 1) + modelVoSuffix.toLowerCase() + "." + HumpOrLineUtil.stringToFirstOneUpperCase(modelVoPreffix.toLowerCase()) + modelName + HumpOrLineUtil.stringToFirstOneUpperCase(modelVoSuffix.toLowerCase());

        // 创建 baseResultMapVo
        XmlElement baseResultMapVo = new XmlElement("resultMap");
        baseResultMapVo.addAttribute(new Attribute("id", "BaseResultMapVo"));
        baseResultMapVo.addAttribute(new Attribute("extends", "BaseResultMap"));
        baseResultMapVo.addAttribute(new Attribute("type", classVoPath));
        baseResultMapVo.addElement(new TextElement(""));
        parentElement.addElement(baseResultMapVo);

        XmlElement columnSql = new XmlElement("sql");
        parentElement.addElement(columnSql);

        // 公用include
        XmlElement where = new XmlElement("where");
        XmlElement include = new XmlElement("include");
        include.addAttribute(new Attribute("refid", "conditionSql"));
        where.addElement(include);

        // 生成新增
        insertSelective(parentElement);

        // 生成批量新增
        insertList(parentElement);

        // 生成修改
        updateByPrimaryKeySelective(parentElement);

        // 生成批量修改
        updateList(parentElement);

        // 生成 delete
        delete(parentElement);

        // 生成 batchDeleteList
        batchDeleteList(parentElement);

        // 增加 selectByParam
        selectByPrimaryKey(parentElement, selectText);
        isExist(parentElement, isExistText);
        selectByParam(parentElement, selectText, where);
        selectByRow(parentElement, selectTextRow, where);

        // 增加 findPageList
        findPageList(parentElement, selectText, where, sb);

        // 增加 findPageListCount
        findPageListCount(parentElement, where);

        // 生成 findByList
        findByList(parentElement, selectText, where);

        // 生成 fuzzyConditionSql
        fuzzyConditionSql(parentElement);

        // 生成 conditionSql
        conditionSql(parentElement);

        // 生成 sqlColumn
        sqlColumn(columnSql);
    }

    //生成 insertSelective
    private void insertSelective(XmlElement parentElement) {
        // 增加 insertSelective
        XmlElement insertSelective = new XmlElement("insert");
        insertSelective.addAttribute(new Attribute("id", "insertSelective"));
//        String parameterType;
//
//        if (introspectedTable.getRules().generateRecordWithBLOBsClass()) {
//            parameterType = introspectedTable.getRecordWithBLOBsType();
//        } else {
//            parameterType = introspectedTable.getBaseRecordType();
//        }

        insertSelective.addAttribute(new Attribute("parameterType", classVoPath));
        insertSelective.addAttribute(new Attribute("useGeneratedKeys", "true"));
        for (IntrospectedColumn introspectedColumn : introspectedTable.getPrimaryKeyColumns()) {
            insertSelective.addAttribute(new Attribute("keyProperty", introspectedColumn.getJavaProperty()));
        }

        StringBuilder sb = new StringBuilder();

        sb.append("insert into ");
        sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        insertSelective.addElement(new TextElement(sb.toString()));

        XmlElement fieldElement = new XmlElement("trim"); //设置trim标签
        fieldElement.addAttribute(new Attribute("prefix", "(")); //添加where和and
        fieldElement.addAttribute(new Attribute("suffix", ") ")); //添加where和and
        fieldElement.addAttribute(new Attribute("suffixOverrides", ",")); //添加where和and

        XmlElement valueElement = new XmlElement("trim"); //设置trim标签
        valueElement.addAttribute(new Attribute("prefix", "values (")); //添加where和and
        valueElement.addAttribute(new Attribute("suffix", ")")); //添加where和and
        valueElement.addAttribute(new Attribute("suffixOverrides", ",")); //添加where和and

        StringBuilder field = new StringBuilder();
        StringBuilder value = new StringBuilder();


        for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
//            if (filterMap.containsKey(introspectedColumn.getJavaProperty())) {
//                continue;
//            }
            XmlElement fieldNotNullElement = new XmlElement("if"); //
            XmlElement valueNotNullElement = new XmlElement("if"); //
            field.setLength(0);
            field.append(introspectedColumn.getJavaProperty());
            field.append(" != null");
            value.setLength(0);
            value.append(introspectedColumn.getJavaProperty());
            value.append(" != null");
            if (jdbcTypeMap.containsKey(introspectedColumn.getJdbcTypeName())) {
                field.append(" and ");
                field.append(introspectedColumn.getJavaProperty());
                field.append(" != ''");
                value.append(" and ");
                value.append(introspectedColumn.getJavaProperty());
                value.append(" != ''");
            }
            fieldNotNullElement.addAttribute(new Attribute("test", field.toString()));
            valueNotNullElement.addAttribute(new Attribute("test", field.toString()));
            // 添加字段名
            field.setLength(0);
            field.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            field.append(",");
            // 添加实体类变量
            value.setLength(0);
            value.append(FormattingUtilities.getParameterClause(introspectedColumn));
            value.append(",");

            fieldNotNullElement.addElement(new TextElement(field.toString()));
            valueNotNullElement.addElement(new TextElement(value.toString()));
            fieldElement.addElement(fieldNotNullElement);
            valueElement.addElement(valueNotNullElement);
        }
        insertSelective.addElement(fieldElement);
        insertSelective.addElement(valueElement);
        parentElement.addElement(insertSelective);
    }

    //生成 insertList
    private void insertList(XmlElement parentElement) {
        // 增加 insertList
        XmlElement insertList = new XmlElement("insert");
        insertList.addAttribute(new Attribute("id", "insertList"));

        insertList.addAttribute(new Attribute("parameterType", "java.util.List"));
        insertList.addAttribute(new Attribute("useGeneratedKeys", "true"));
        for (IntrospectedColumn introspectedColumn : introspectedTable.getPrimaryKeyColumns()) {
            insertList.addAttribute(new Attribute("keyProperty", introspectedColumn.getJavaProperty()));
        }

        StringBuilder sb = new StringBuilder();

        sb.append("insert into ");
        sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        insertList.addElement(new TextElement(sb.toString()));


        XmlElement valueElement = new XmlElement("foreach"); //设置 foreach 标签
        valueElement.addAttribute(new Attribute("collection", "list")); //添加 collection
        valueElement.addAttribute(new Attribute("item", "item")); //添加 item
        valueElement.addAttribute(new Attribute("index", "index")); //添加 index
        valueElement.addAttribute(new Attribute("separator", "union all")); //添加 separator

        StringBuilder field = new StringBuilder();
        StringBuilder value = new StringBuilder();

        field.append("(");
        valueElement.addElement(new TextElement("SELECT"));
        for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
            if (insertFilterMap.containsKey(introspectedColumn.getJavaProperty())) {
                continue;
            }
            field.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            field.append(", ");
            // 添加实体类变量
            value.append(FormattingUtilities.getParameterClause(introspectedColumn, "item."));
            value.append(", ");
        }
        value.deleteCharAt(value.length() - 1);
        value.deleteCharAt(value.length() - 1);
        field.deleteCharAt(field.length() - 1);
        field.deleteCharAt(field.length() - 1);
        field.append(")");
        valueElement.addElement(new TextElement(value.toString()));
        valueElement.addElement(new TextElement("FROM dual"));
        insertList.addElement(new TextElement(field.toString()));
        insertList.addElement(valueElement);
        parentElement.addElement(insertList);
    }

    //生成 updateByPrimaryKeySelective
    private void updateByPrimaryKeySelective(XmlElement parentElement) {
        // 增加 updateByPrimaryKeySelective
        XmlElement updateByPrimaryKeySelective = new XmlElement("update");
        updateByPrimaryKeySelective.addAttribute(new Attribute("id", "updateByPrimaryKeySelective"));
//        String parameterType;
//
//        if (introspectedTable.getRules().generateRecordWithBLOBsClass()) {
//            parameterType = introspectedTable.getRecordWithBLOBsType();
//        } else {
//            parameterType = introspectedTable.getBaseRecordType();
//        }

        updateByPrimaryKeySelective.addAttribute(new Attribute("parameterType", classVoPath));

        context.getCommentGenerator().addComment(updateByPrimaryKeySelective);
        XmlElement fieldElement = new XmlElement("set"); //设置trim标签

        StringBuilder sb = new StringBuilder();
        sb.append("update ");
        sb.append(this.introspectedTable.getFullyQualifiedTableNameAtRuntime());
        updateByPrimaryKeySelective.addElement(new TextElement(sb.toString()));
        StringBuilder tenantId = new StringBuilder();
        StringBuilder userId = new StringBuilder();
        for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
            if (introspectedColumn.getJavaProperty().equalsIgnoreCase("tenantId")) {
                tenantId.append("<if test=\"tenantId != null\">and ");
                tenantId.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                tenantId.append(" = ");
                tenantId.append(FormattingUtilities.getParameterClause(introspectedColumn));
                tenantId.append("</if>");
                if (deleteMap.size() == NumeralUtil.POSITIVE_ZERO) {
                    break;
                }
                continue;
            }
            if (updateFilterMap.containsKey(introspectedColumn.getJavaProperty())) {
                continue;
            }
            if (introspectedColumn.getJavaProperty().equalsIgnoreCase("userId")) {
                userId.append("and ");
                userId.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                userId.append(" = ");
                userId.append(FormattingUtilities.getParameterClause(introspectedColumn));
            }
            XmlElement selectNotNullElement = new XmlElement("if"); //
            sb.setLength(0);
            sb.append(introspectedColumn.getJavaProperty());
            sb.append(" != null");
            if (jdbcTypeMap.containsKey(introspectedColumn.getJdbcTypeName())) {
                sb.append(" and ");
                sb.append(introspectedColumn.getJavaProperty());
                sb.append(" != ''");
            }
            selectNotNullElement.addAttribute(new Attribute("test", sb.toString()));
            // 添加字段名
            sb.setLength(0);
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" = ");
            sb.append(FormattingUtilities.getParameterClause(introspectedColumn));
            sb.append(",");
            selectNotNullElement.addElement(new TextElement(sb.toString()));
            fieldElement.addElement(selectNotNullElement);
        }
        updateByPrimaryKeySelective.addElement(fieldElement);
        buildPrimaryKeyWhereClause().forEach(updateByPrimaryKeySelective::addElement);

        if (tenantId.length() > 0) {
            updateByPrimaryKeySelective.addElement(new TextElement(tenantId.toString()));
        }
        if ("api".equalsIgnoreCase(item) && userId.length() > 0) {
            updateByPrimaryKeySelective.addElement(new TextElement(userId.toString()));
        }
        if (context.getPlugins().sqlMapUpdateByPrimaryKeySelectiveElementGenerated(updateByPrimaryKeySelective, introspectedTable)) {
            parentElement.addElement(updateByPrimaryKeySelective);
        }
    }

    //生成 updateList
    private void updateList(XmlElement parentElement) {
        // 增加 updateList
        XmlElement updateList = new XmlElement("update");
        updateList.addAttribute(new Attribute("id", "updateList"));
        updateList.addAttribute(new Attribute("parameterType", "java.util.List"));
        context.getCommentGenerator().addComment(updateList);

        XmlElement foreachElement = new XmlElement("foreach"); //设置 foreach 标签
        foreachElement.addAttribute(new Attribute("collection", "list")); //添加 collection
        foreachElement.addAttribute(new Attribute("item", "item")); //添加 item
        foreachElement.addAttribute(new Attribute("index", "index")); //添加 index
        foreachElement.addAttribute(new Attribute("open", "")); //添加 open
        foreachElement.addAttribute(new Attribute("close", "")); //添加 close
        foreachElement.addAttribute(new Attribute("separator", ";")); //添加 close

        XmlElement fieldElement = new XmlElement("set"); //设置set标签

        StringBuilder sb = new StringBuilder();
        sb.append("update ");
        sb.append(this.introspectedTable.getFullyQualifiedTableNameAtRuntime());
        foreachElement.addElement(new TextElement(sb.toString()));
        StringBuilder tenantId = new StringBuilder();
        StringBuilder userId = new StringBuilder();
        for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
            if (introspectedColumn.getJavaProperty().equalsIgnoreCase("tenantId")) {
                tenantId.append("<if test=\"item.tenantId != null\">and ");
                tenantId.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                tenantId.append(" = ");
                tenantId.append(FormattingUtilities.getParameterClause(introspectedColumn, "item."));
                tenantId.append("</if>");
                if (deleteMap.size() == NumeralUtil.POSITIVE_ZERO) {
                    break;
                }
                continue;
            }

            if (updateFilterMap.containsKey(introspectedColumn.getJavaProperty())) {
                continue;
            }
            if (introspectedColumn.getJavaProperty().equalsIgnoreCase("userId")) {
                userId.append("and ");
                userId.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                userId.append(" = ");
                userId.append(FormattingUtilities.getParameterClause(introspectedColumn, "item."));
            }
            XmlElement selectNotNullElement = new XmlElement("if"); //
            sb.setLength(0);
            sb.append("item.");
            sb.append(introspectedColumn.getJavaProperty());
            sb.append(" != null");
            if (jdbcTypeMap.containsKey(introspectedColumn.getJdbcTypeName())) {
                sb.append(" and ");
                sb.append("item.");
                sb.append(introspectedColumn.getJavaProperty());
                sb.append(" != ''");
            }
            selectNotNullElement.addAttribute(new Attribute("test", sb.toString()));
            // 添加字段名
            sb.setLength(0);
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" = ");
            sb.append(FormattingUtilities.getParameterClause(introspectedColumn, "item."));
            sb.append(",");
            selectNotNullElement.addElement(new TextElement(sb.toString()));
            fieldElement.addElement(selectNotNullElement);
        }
        foreachElement.addElement(fieldElement);
        foreachElement.addElement(new TextElement("where "));
        for (IntrospectedColumn introspectedColumn : introspectedTable.getPrimaryKeyColumns()) {
            // 添加字段名
            sb.setLength(0);
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" = ");
            sb.append(FormattingUtilities.getParameterClause(introspectedColumn, "item."));
            foreachElement.addElement(new TextElement(sb.toString()));
        }
        if (tenantId.length() > 0) {
            foreachElement.addElement(new TextElement(tenantId.toString()));
        }
        if ("api".equalsIgnoreCase(item) && userId.length() > 0) {
            foreachElement.addElement(new TextElement(userId.toString()));
        }
        updateList.addElement(foreachElement);
        parentElement.addElement(updateList);
//        buildPrimaryKeyWhereClause().forEach(updateList::addElement);
    }

    //生成 delete
    private void delete(XmlElement parentElement) {
        // 增加 delete
        XmlElement delete = new XmlElement("update");

        delete.addAttribute(new Attribute("id", "delete"));

//        String parameterType;
//
//        if (introspectedTable.getRules().generateRecordWithBLOBsClass()) {
//            parameterType = introspectedTable.getRecordWithBLOBsType();
//        } else {
//            parameterType = introspectedTable.getBaseRecordType();
//        }

        delete.addAttribute(new Attribute("parameterType", classVoPath));

        context.getCommentGenerator().addComment(delete);

        StringBuilder sb = new StringBuilder();

        sb.append("update ");
        sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        delete.addElement(new TextElement(sb.toString()));

        delete.addElement(new TextElement("set"));

        StringBuilder tenantId = new StringBuilder();
        StringBuilder userId = new StringBuilder();
        for (IntrospectedColumn introspectedColumn : ListUtilities.removeGeneratedAlwaysColumns(introspectedTable.getNonPrimaryKeyColumns())) {
            if (introspectedColumn.getJavaProperty().equalsIgnoreCase("userId")) {
                userId.append("and ");
                userId.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                userId.append(" = ");
                userId.append(FormattingUtilities.getParameterClause(introspectedColumn));
            }
            if (introspectedColumn.getJavaProperty().equalsIgnoreCase("tenantId")) {
                tenantId.append("<if test=\"tenantId != null\">and ");
                tenantId.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                tenantId.append(" = ");
                tenantId.append(FormattingUtilities.getParameterClause(introspectedColumn));
                tenantId.append("</if>");
                if (deleteMap.size() == NumeralUtil.POSITIVE_ZERO) {
                    break;
                }
                continue;
            }
            if (!deleteMap.containsKey(introspectedColumn.getJavaProperty())) {
                continue;
            }
            sb.setLength(0);
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            sb.append(" = ");
            sb.append(FormattingUtilities.getParameterClause(introspectedColumn));
            if (deleteMap.size() != NumeralUtil.POSITIVE_ONE) {
                sb.append(',');
            }
            delete.addElement(new TextElement(sb.toString()));
            deleteMap.remove(introspectedColumn.getJavaProperty());
        }

        buildPrimaryKeyWhereClause().forEach(delete::addElement);

        if (tenantId.length() > 0) {
            delete.addElement(new TextElement(tenantId.toString()));
        }
        if ("api".equalsIgnoreCase(item) && userId.length() > 0) {
            delete.addElement(new TextElement(userId.toString()));
        }
        operaterStatus(delete);
        if (context.getPlugins().sqlMapUpdateByPrimaryKeySelectiveElementGenerated(delete, introspectedTable)) {
            parentElement.addElement(delete);
        }

    }


    private void operaterStatus(XmlElement xmlElement) {
        for (IntrospectedColumn item : introspectedTable.getAllColumns()) {
            if ("operaterStatus".equalsIgnoreCase(item.getJavaProperty())) {
                xmlElement.addElement(new TextElement(" and OPERATER_STATUS > 0"));
                break;
            }
        }
    }

    //生成 batchDeleteList
    private void batchDeleteList(XmlElement parentElement) {
        // 增加 batchDeleteList
        XmlElement batchDeleteList = new XmlElement("update");

        batchDeleteList.addAttribute(new Attribute("id", "batchDeleteList"));

//        String parameterType;
//
//        if (introspectedTable.getRules().generateRecordWithBLOBsClass()) {
//            parameterType = introspectedTable.getRecordWithBLOBsType();
//        } else {
//            parameterType = introspectedTable.getBaseRecordType();
//        }

        batchDeleteList.addAttribute(new Attribute("parameterType", classVoPath));

        context.getCommentGenerator().addComment(batchDeleteList);

        StringBuilder sb = new StringBuilder();

        sb.append("update ");
        sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        batchDeleteList.addElement(new TextElement(sb.toString()));

        batchDeleteList.addElement(new TextElement("set"));

        StringBuilder tenantId = new StringBuilder();
        StringBuilder userId = new StringBuilder();
        for (IntrospectedColumn introspectedColumn : ListUtilities.removeGeneratedAlwaysColumns(introspectedTable.getNonPrimaryKeyColumns())) {
            if (introspectedColumn.getJavaProperty().equalsIgnoreCase("userId")) {
                userId.append("and ");
                userId.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                userId.append(" = ");
                userId.append(FormattingUtilities.getParameterClause(introspectedColumn));
            }
            if (introspectedColumn.getJavaProperty().equalsIgnoreCase("tenantId")) {
                tenantId.append("<if test=\"tenantId != null\">and ");
                tenantId.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                tenantId.append(" = ");
                tenantId.append(FormattingUtilities.getParameterClause(introspectedColumn));
                tenantId.append("</if>");
                if (batchDeleteListMap.size() == NumeralUtil.POSITIVE_ZERO) {
                    break;
                }
                continue;
            }
            if (!batchDeleteListMap.containsKey(introspectedColumn.getJavaProperty())) {
                continue;
            }
            sb.setLength(0);
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            sb.append(" = ");
            sb.append(FormattingUtilities.getParameterClause(introspectedColumn));
            if (batchDeleteListMap.size() != NumeralUtil.POSITIVE_ONE) {
                sb.append(',');
            }
            batchDeleteList.addElement(new TextElement(sb.toString()));
            batchDeleteListMap.remove(introspectedColumn.getJavaProperty());
        }

        batchDeleteList.addElement(new TextElement("WHERE ID IN "));
        batchDeleteList.addElement(new TextElement("<foreach collection=\"idList\" item=\"item\" index=\"index\" separator=\",\" open=\"(\" close=\")\">"));
        batchDeleteList.addElement(new TextElement("#{item}"));
        batchDeleteList.addElement(new TextElement("</foreach>"));

        if (tenantId.length() > 0) {
            batchDeleteList.addElement(new TextElement(tenantId.toString()));
        }
        if ("api".equalsIgnoreCase(item) && userId.length() > 0) {
            batchDeleteList.addElement(new TextElement(userId.toString()));
        }

        operaterStatus(batchDeleteList);
        if (context.getPlugins().sqlMapUpdateByPrimaryKeySelectiveElementGenerated(batchDeleteList, introspectedTable)) {
            parentElement.addElement(batchDeleteList);
        }

    }

    //生成 selectByPrimaryKey
    private void selectByPrimaryKey(XmlElement parentElement, TextElement selectText) {
        // 增加 selectByPrimaryKey
        XmlElement selectByPrimaryKey = new XmlElement("select");
        selectByPrimaryKey.addAttribute(new Attribute("id", "selectByPrimaryKey"));
        selectByPrimaryKey.addAttribute(new Attribute("resultMap", "BaseResultMapVo"));
        selectByPrimaryKey.addAttribute(new Attribute("parameterType", "java.lang.Long"));
        selectByPrimaryKey.addElement(selectText);
        selectByPrimaryKey.addElement(new TextElement("where "));
        StringBuilder sb = new StringBuilder();
        for (IntrospectedColumn introspectedColumn : introspectedTable.getPrimaryKeyColumns()) {
            // 添加字段名
            sb.setLength(0);
            sb.append("p.");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" = ");
            sb.append(FormattingUtilities.getParameterClause(introspectedColumn));
            selectByPrimaryKey.addElement(new TextElement(sb.toString()));
        }
        for (IntrospectedColumn item : introspectedTable.getAllColumns()) {
            if ("operaterStatus".equalsIgnoreCase(item.getJavaProperty())) {
                selectByPrimaryKey.addElement(new TextElement(" and p.OPERATER_STATUS > 0"));
                break;
            }
        }
        parentElement.addElement(selectByPrimaryKey);
    }

    //生成 isExist
    private void isExist(XmlElement parentElement, TextElement selectText) {
        // 增加 isExist
        XmlElement isExist = new XmlElement("select");
        isExist.addAttribute(new Attribute("id", "isExist"));
        isExist.addAttribute(new Attribute("resultType", "java.lang.Integer"));
        isExist.addAttribute(new Attribute("parameterType", classVoPath));
        isExist.addElement(selectText);
        StringBuilder sb = new StringBuilder();
        XmlElement where = new XmlElement("where"); //
        for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
            if (isExistFilterMap.containsKey(introspectedColumn.getJavaProperty())) {
                isExistFilterMap.remove(introspectedColumn.getJavaProperty());
                continue;
            }

            XmlElement selectNotNullElement = new XmlElement("if"); //
            sb.setLength(0);
            if ("id".equalsIgnoreCase(introspectedColumn.getJavaProperty())) {
                sb.append(introspectedColumn.getJavaProperty());
                sb.append(" != null");
                selectNotNullElement.addAttribute(new Attribute("test", sb.toString()));
                sb.setLength(0);
                // 添加and
                sb.append(" and ");
                // 添加别名t
                sb.append("p.");
                sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                // 添加等号
                sb.append(" != ");
                sb.append(FormattingUtilities.getParameterClause(introspectedColumn));
                selectNotNullElement.addElement(new TextElement(sb.toString()));
                where.addElement(selectNotNullElement);
                continue;
            }


            sb.append(introspectedColumn.getJavaProperty());
            sb.append(" != null");
            if (jdbcTypeMap.containsKey(introspectedColumn.getJdbcTypeName())) {
                sb.append(" and ");
                sb.append(introspectedColumn.getJavaProperty());
                sb.append(" != ''");
            }
            selectNotNullElement.addAttribute(new Attribute("test", sb.toString()));
            sb.setLength(0);
            // 添加and
            sb.append(" and ");
            // 添加别名t
            sb.append("p.");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" = ");
            sb.append(FormattingUtilities.getParameterClause(introspectedColumn));
            selectNotNullElement.addElement(new TextElement(sb.toString()));
            where.addElement(selectNotNullElement);
        }
        isExist.addElement(where);
//        isExist.addElement(new TextElement("limit 1"));
        parentElement.addElement(isExist);
    }

    //生成 selectByParam
    private void selectByParam(XmlElement parentElement, TextElement selectText, XmlElement include) {
        // 增加 selectByParam
        XmlElement selectByParam = new XmlElement("select");
        selectByParam.addAttribute(new Attribute("id", "selectByParam"));
        selectByParam.addAttribute(new Attribute("resultMap", "BaseResultMapVo"));
        selectByParam.addAttribute(new Attribute("parameterType", classVoPath));
        selectByParam.addElement(selectText);
        selectByParam.addElement(include);
        selectByParam.addElement(new TextElement("limit 1"));
        parentElement.addElement(selectByParam);
    }

    //生成 selectByRow
    private void selectByRow(XmlElement parentElement, TextElement selectText, XmlElement include) {
        // 增加 selectByRow
        XmlElement selectByRow = new XmlElement("select");
        selectByRow.addAttribute(new Attribute("id", "selectByRow"));
        selectByRow.addAttribute(new Attribute("resultMap", "BaseResultMapVo"));
        selectByRow.addAttribute(new Attribute("parameterType", classVoPath));
        selectByRow.addElement(selectText);
        selectByRow.addElement(include);
        selectByRow.addElement(new TextElement("limit 1"));
        parentElement.addElement(selectByRow);
    }


    //生成 findPageList
    private void findPageList(XmlElement parentElement, TextElement selectText, XmlElement include, StringBuilder sb) {
        // 增加 findPageList
        XmlElement findPageList = new XmlElement("select");
        findPageList.addAttribute(new Attribute("id", "findPageList"));
        findPageList.addAttribute(new Attribute("resultMap", "BaseResultMapVo"));
        findPageList.addAttribute(new Attribute("parameterType", classVoPath));
        findPageList.addElement(selectText);
        findPageList.addElement(include);
        //sortElement
        XmlElement sortElement = new XmlElement("if");
        sb.setLength(0);
//        sb.append("sort != null and sort != ''");
//        sortElement.addAttribute(new Attribute("test", sb.toString()));
//        sb.setLength(0);
//        sb.append("order by ${sort}");
//        sortElement.addElement(new TextElement(sb.toString()));
//        //orderElement
//        XmlElement orderElement = new XmlElement("if");
//        sb.setLength(0);
//        sb.append("order != null and order != ''");
//        orderElement.addAttribute(new Attribute("test", sb.toString()));
//        sb.setLength(0);
//        sb.append("${order}");
//        orderElement.addElement(new TextElement(sb.toString()));
//        sortElement.addElement(orderElement);
//        findPageList.addElement(sortElement);
        sb.append("<include refid=\"BaseMapper.publicSortAndOrder\"/>");
        findPageList.addElement(new TextElement(sb.toString()));

        //limit
        sb.setLength(0);
//        sb.append("limit #{offset}, #{limit}");
//        findPageList.addElement(new TextElement(sb.toString()));
//        parentElement.addElement(findPageList);
        sb.append("<include refid=\"BaseMapper.publicOffsetAndLimit\"/>");
        findPageList.addElement(new TextElement(sb.toString()));
        parentElement.addElement(findPageList);

    }

    //生成 findPageListCount
    private void findPageListCount(XmlElement parentElement, XmlElement include) {
        // 增加 findPageListCount
        StringBuilder findPageListCountSql = new StringBuilder();
        findPageListCountSql.append("    select ");
        findPageListCountSql.append("\n        COUNT(p.ID) ");
        findPageListCountSql.append("\n        from ");
        findPageListCountSql.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
        findPageListCountSql.append(" p ");
        TextElement findPageListCountSqlText = new TextElement(findPageListCountSql.toString());
        XmlElement findPageListCount = new XmlElement("select");
        findPageListCount.addAttribute(new Attribute("id", "findPageListCount"));
        findPageListCount.addAttribute(new Attribute("resultType", "INTEGER"));
        findPageListCount.addAttribute(new Attribute("parameterType", classVoPath));
        findPageListCount.addElement(findPageListCountSqlText);
        findPageListCount.addElement(include);
        parentElement.addElement(findPageListCount);
    }

    //生成 findByList
    private void findByList(XmlElement parentElement, TextElement selectText, XmlElement include) {
        // 增加 findByList
        XmlElement findByList = new XmlElement("select");
        findByList.addAttribute(new Attribute("id", "findByList"));
        findByList.addAttribute(new Attribute("resultMap", "BaseResultMapVo"));
        findByList.addAttribute(new Attribute("parameterType", classVoPath));
        findByList.addElement(selectText);
        findByList.addElement(include);
        parentElement.addElement(findByList);
    }

    // 生成 fuzzyConditionSql
    private void fuzzyConditionSql(XmlElement parentElement) {
        StringBuilder sb = new StringBuilder();
        // 增加 fuzzyConditionSql
//        sb.setLength(0);
        XmlElement fuzzyConditionSql = new XmlElement("sql");
        fuzzyConditionSql.addAttribute(new Attribute("id", "fuzzyConditionSql"));
////        //在这里添加where条件
//        XmlElement selectTrimElement = new XmlElement("trim"); //设置trim标签
////        selectTrimElement.addAttribute(new Attribute("prefix", "WHERE"));
//        selectTrimElement.addAttribute(new Attribute("prefixOverrides", "AND | OR")); //添加where和and


        XmlElement searchConditionSql = new XmlElement("sql");
        searchConditionSql.addAttribute(new Attribute("id", "searchConditionSql"));
//        XmlElement searchSelectTrimElement = new XmlElement("trim"); //设置trim标签
////        selectTrimElement.addAttribute(new Attribute("prefix", "WHERE"));
//        searchSelectTrimElement.addAttribute(new Attribute("prefixOverrides", "AND | OR")); //添加where和and
//        //在这里添加if条件
        XmlElement searchSelectIfElement = new XmlElement("if"); //设置trim标签
//        selectTrimElement.addAttribute(new Attribute("prefix", "WHERE"));
        searchSelectIfElement.addAttribute(new Attribute("test", "search != null and search != ''")); //添加where和and
        searchSelectIfElement.addElement(new TextElement("AND ("));
        for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
            if (filterMap.containsKey(introspectedColumn.getJavaProperty()) || columnMap.containsKey(introspectedColumn.getJavaProperty())) {
                continue;
            }
            XmlElement selectNotNullElement = new XmlElement("if");
            sb.setLength(0);
            sb.append("fuzzyType == '");
            sb.append(introspectedColumn.getJavaProperty());
            sb.append("'");
            selectNotNullElement.addAttribute(new Attribute("test", sb.toString()));
            sb.setLength(0);
            // 添加and
            sb.append(" and ");
            // 添加别名t
            sb.append("p.");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" LIKE CONCAT('%', #{fuzzyValue}, '%')");
            selectNotNullElement.addElement(new TextElement(sb.toString()));

            sb.setLength(0);
            if (searchSelectIfElement.getElements().size() > 1) {
                // 添加or
                sb.append(" or ");
            } else {
                sb.append(" ");
            }
            // 添加别名t
            sb.append("p.");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" LIKE CONCAT('%', #{search}, '%')");
//            selectTrimElement.addElement(selectNotNullElement);
            fuzzyConditionSql.addElement(selectNotNullElement);
            searchSelectIfElement.addElement(new TextElement(sb.toString()));
        }
//        fuzzyConditionSql.addElement(selectTrimElement);
        searchSelectIfElement.addElement(new TextElement(")"));
//        searchSelectTrimElement.addElement(searchSelectIfElement);
//        searchConditionSql.addElement(searchSelectTrimElement);
        searchConditionSql.addElement(searchSelectIfElement);
        parentElement.addElement(fuzzyConditionSql);
        parentElement.addElement(searchConditionSql);
    }


    // 生成 conditionSql
    private void conditionSql(XmlElement parentElement) {
        StringBuilder sb = new StringBuilder();

        // 增加 conditionSql
        sb.setLength(0);
        XmlElement conditionSql = new XmlElement("sql");
        conditionSql.addAttribute(new Attribute("id", "conditionSql"));
//        //在这里添加where条件
//        XmlElement selectTrimElement = new XmlElement("trim"); //设置trim标签
////        selectTrimElement.addAttribute(new Attribute("prefix", "WHERE"));
//        selectTrimElement.addAttribute(new Attribute("prefixOverrides", "AND | OR")); //添加where和and

        //关键字模糊搜索
        XmlElement vagueConditionSql = new XmlElement("sql");
        vagueConditionSql.addAttribute(new Attribute("id", "vagueConditionSql"));
        //在这里添加where条件
//        XmlElement vagueSelectTrimElement = new XmlElement("trim"); //设置trim标签
////        selectTrimElement.addAttribute(new Attribute("prefix", "WHERE"));
//        vagueSelectTrimElement.addAttribute(new Attribute("prefixOverrides", "AND | OR")); //添加where和and

//        XmlElement includeBaseMapperPublicWhere = new XmlElement("include");
//        includeBaseMapperPublicWhere.addAttribute(new Attribute("refid", "BaseMapper.publicWhere"));
//        XmlElement includeBaseMapperPublicWhereCreateTime = new XmlElement("include");
//        includeBaseMapperPublicWhereCreateTime.addAttribute(new Attribute("refid", "BaseMapper.publicWhereCreateTime"));


//        selectTrimElement.addElement(includeBaseMapperPublicWhere);
//        selectTrimElement.addElement(includeBaseMapperPublicWhereCreateTime);

//        conditionSql.addElement(includeBaseMapperPublicWhere);
//        conditionSql.addElement(includeBaseMapperPublicWhereCreateTime);

        XmlElement publicWhereId = new XmlElement("include");
        publicWhereId.addAttribute(new Attribute("refid", "BaseMapper.publicWhereId"));
        XmlElement publicWhereStatus = new XmlElement("include");
        publicWhereStatus.addAttribute(new Attribute("refid", "BaseMapper.publicWhereStatus"));
        XmlElement publicWhereUserId = new XmlElement("include");
        publicWhereUserId.addAttribute(new Attribute("refid", "BaseMapper.publicWhereUserId"));
        XmlElement publicWhereCreateTime = new XmlElement("include");
        publicWhereCreateTime.addAttribute(new Attribute("refid", "BaseMapper.publicWhereCreateTime"));

        if (introspectedTable.getPrimaryKeyColumns() != null && introspectedTable.getPrimaryKeyColumns().size() > NumeralUtil.POSITIVE_ZERO) {
            conditionSql.addElement(publicWhereId);
            vagueConditionSql.addElement(publicWhereId);
        }


        for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
            if (columnMap.containsKey(introspectedColumn.getJavaProperty())) {
                continue;
            }
            if ("operaterStatus".equalsIgnoreCase(introspectedColumn.getJavaProperty())) {
                isPublicWhereStatus = true;
                isStatus = true;
                continue;
            }
            if ("createId".equalsIgnoreCase(introspectedColumn.getJavaProperty())) {
                isPublicWhereUserId = true;
                isStatus = true;
                continue;
            }
            if ("createTime".equalsIgnoreCase(introspectedColumn.getJavaProperty())) {
                isPublicWhereCreateTime = true;
                isStatus = true;
                continue;
            }
            if (filterMap.containsKey(introspectedColumn.getJavaProperty())) {
                isStatus = true;
                continue;
            }
            XmlElement selectNotNullElement = new XmlElement("if"); //
            XmlElement vagueNotNullElement = new XmlElement("if"); //
            sb.setLength(0);
            sb.append(introspectedColumn.getJavaProperty());
            sb.append(" != null");
            if (jdbcTypeMap.containsKey(introspectedColumn.getJdbcTypeName())) {
                sb.append(" and ");
                sb.append(introspectedColumn.getJavaProperty());
                sb.append(" != ''");
            }
            selectNotNullElement.addAttribute(new Attribute("test", sb.toString()));
            vagueNotNullElement.addAttribute(new Attribute("test", sb.toString()));
            sb.setLength(0);
            // 添加and
            sb.append(" and ");
            // 添加别名t
            sb.append("p.");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" = ");
            sb.append(FormattingUtilities.getParameterClause(introspectedColumn));
            selectNotNullElement.addElement(new TextElement(sb.toString()));

            sb.setLength(0);
            // 添加and
            sb.append(" and ");
            // 添加别名t
            sb.append("p.");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            // 添加等号
            sb.append(" LIKE CONCAT('%', ");
            sb.append(FormattingUtilities.getParameterClause(introspectedColumn));
            sb.append(", '%') ");
            vagueNotNullElement.addElement(new TextElement(sb.toString()));

//            selectTrimElement.addElement(selectNotNullElement);
//            vagueSelectTrimElement.addElement(vagueNotNullElement);
            conditionSql.addElement(selectNotNullElement);
            vagueConditionSql.addElement(vagueNotNullElement);
        }
        if (isStatus) {
            if (isPublicWhereStatus) {
                conditionSql.addElement(publicWhereStatus);
                vagueConditionSql.addElement(publicWhereStatus);
            }
            if (isPublicWhereUserId && "back".equalsIgnoreCase(item)) {
                conditionSql.addElement(publicWhereUserId);
                vagueConditionSql.addElement(publicWhereUserId);
            }
            if (isPublicWhereCreateTime) {
                conditionSql.addElement(publicWhereCreateTime);
                vagueConditionSql.addElement(publicWhereCreateTime);
            }
        }
//        conditionSql.addElement(selectTrimElement);
//        vagueConditionSql.addElement(vagueSelectTrimElement);
        parentElement.addElement(conditionSql);
        parentElement.addElement(vagueConditionSql);
    }


    // 生成 sqlColumn
    private void sqlColumn(XmlElement columnSql) {
        StringBuilder sqlColumn = new StringBuilder();
        for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
            if (columnMap.containsKey(introspectedColumn.getJavaProperty())) {
                sqlColumn.append("p.").append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            }
            if (filterMap.containsKey(introspectedColumn.getJavaProperty()) || filterMap.containsKey(introspectedColumn.getJdbcTypeName()) || columnMap.containsKey(introspectedColumn.getJavaProperty()) || columnMap.containsKey(introspectedColumn.getJdbcTypeName())) {
                continue;
            }
            if (sqlColumn.length() > NumeralUtil.POSITIVE_ZERO) {
                sqlColumn.append(", p.").append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn)).append("");
            } else {
                sqlColumn.append("p.").append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn)).append("");
            }
        }

        columnSql.addAttribute(new Attribute("id", "Base_Column_List"));
        columnSql.addElement(new TextElement(sqlColumn.toString()));
    }



}
